package com.woniu.tmsvehicle.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniu.tmscommons.entity.Driver;
import com.woniu.tmscommons.entity.Vehicle;
import com.woniu.tmscommons.enums.DriverStatus;
import com.woniu.tmscommons.enums.VehicleStatus;
import com.woniu.tmscommons.feign.FeignOrderService;
import com.woniu.tmscommons.response.ResponseResult;
import com.woniu.tmsvehicle.config.MailRabbitConfig;
import com.woniu.tmsvehicle.config.RabbitConfig;
import com.woniu.tmsvehicle.config.SmsRabbitConfig;
import com.woniu.tmsvehicle.mapper.TransportMapper;
import com.woniu.tmsvehicle.producer.RefreshProducer;
import com.woniu.tmsvehicle.service.DriverService;
import com.woniu.tmsvehicle.service.TransportService;
import com.woniu.tmsvehicle.service.VehicleService;
import com.woniu.tmsvehicle.vo.AddrVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TransportServiceImpl implements TransportService {
    @Resource
    private TransportMapper transportMapper;
    @Resource
    private VehicleService vehicleService;
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private DriverService driverService;
    @Resource
    private RefreshProducer refreshProducer;


    @Override
    public List<Driver> findAvailableDriverAndVehicle() {
        List<Driver> drivers = transportMapper.findAvailableDriverAndVehicle();
        return drivers;
    }

    @Value("${txApi.Key}")
    private String txKey;
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String,String> findNearestDriverAndVehicle(String ip) {
        List<Driver> drivers = findAvailableDriverAndVehicle();
        String url = "https://apis.map.qq.com/ws/location/v1/ip?ip=" + ip +
                "&key=" + txKey;
        String res = restTemplate.getForObject(url, String.class);
        log.info("res:{}", res);
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            Map<String,String> map = objectMapper.readValue(res, Map.class);
            return map;
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int findDistance(AddrVo addrVo) {
        String latTo = addrVo.getLatTo();
        String lngTo = addrVo.getLngTo();
        String strTo =latTo + "," + lngTo;

        String latFrom = addrVo.getLatFrom();
        String lngFrom = addrVo.getLngFrom();
        String strFrom = latFrom + "," + lngFrom;

        String url = "https://apis.map.qq.com/ws/direction/v1/driving/?" +
                "from=" + strFrom +
                "&to=" + strTo +
                "&waypoints=39.111,116.112;39.112,116.113" +
                "&output=json&callback=cb" +
                "&policy=LEAST_TIME&key=" + txKey;
        String res = restTemplate.getForObject(url, String.class);
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            Map<String,Object> map = objectMapper.readValue(res, Map.class);
            Map result =(Map) map.get("result");
            List<Map> routes = (List) result.get("routes");
            Map map1 = routes.get(0);
            Integer distance =(Integer) map1.get("distance");
            log.info("distance:{}", distance);
            return distance;
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

//    @Override
//    public Driver findShortestDistance(String latTo, String lngTo) {
//        List<Driver> drivers = findAvailableDriverAndVehicle();
//        List<Integer> distances = new ArrayList<>();
//        //循环把闲置司机的经纬度与目的地经纬度计算距离
//
//        for(Driver driver : drivers){
//            AddrVo addrVo = new AddrVo();
//            addrVo.setLatFrom(driver.getVehicle().getLag().toString());
//            addrVo.setLngFrom(driver.getVehicle().getLng().toString());
//            addrVo.setLatTo(latTo);
//            addrVo.setLngTo(lngTo);
//
//            int distance = findDistance(addrVo);
//            distances.add(distance);
//        }
//        Driver driver = new Driver();
//        for(int i=0;i<distances.size();i++){
//            if(distances.get(i) == Collections.min(distances)){
//                driver =  drivers.get(i);
//            }
//        }
//        return driver;
//    }

    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private FeignOrderService feignOrderService;
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Vehicle findRightVehicle(Double capacity,String senderAddress)  {
        //获取自家所有符合的载重的车辆
        List<Vehicle> vehicles = transportMapper.findRightVehicle(capacity);
        //如果不存在返回空
        if(vehicles.size() ==0){
            return null;
        }
        //获取所有自家司机
        List<Driver> drivers = driverService.findOurDrivers();
        //获取所有自家空闲司机
        List<Driver> availableDrivers = drivers.stream().filter(driver -> driver.getDriverStatus() == DriverStatus.AVAILABLE).collect(Collectors.toList());
        //把司机存入redis
        if (availableDrivers.size()==0){
            for (Driver driver : drivers) {
                redisTemplate.opsForHash().put("myDrivers", "driver:"+driver.getId(), VehicleStatus.INSERVICE.getValue());
            }
        }
        //否则获取空闲的车辆
        List<Vehicle> availableVehicles = vehicles.stream().filter(vehicle -> vehicle.getVehicleStatus() == VehicleStatus.AVAILABLE).collect(Collectors.toList());
        //把空闲车辆的经纬度存入redis
        if (availableVehicles.size()!=0){
            Map<Object, Point> map=new HashMap<>();
            for (Vehicle vehicle : availableVehicles) {
                map.put(vehicle.getId(), new Point(vehicle.getLng().doubleValue(),vehicle.getLag().doubleValue()));
            }
            redisTemplate.opsForGeo().add("vehicle_Position",map);
            //获取离发货地经纬度最近的车辆
            Integer senderAddressPosition = feignOrderService.getSenderAddressPosition(senderAddress).getData();
            Vehicle vehicle = availableVehicles.get(senderAddressPosition);
            if (availableDrivers.size()==0){
                vehicle.setDriver(null);
                vehicle.setDriverId(null);
            }
            //如果有空闲司机
            else {
                vehicle.setDriver(availableDrivers.get(0));
                vehicle.setDriverId(availableDrivers.get(0).getId());
                vehicleService.updateAMsg(vehicle);
            }
            return vehicle;
        }else {
            for (Vehicle vehicle : vehicles) {
                redisTemplate.opsForHash().put("myVehicles", "vehicle:"+vehicle.getId(), VehicleStatus.AVAILABLE.getValue());
                redisTemplate.opsForHash().put("vehicles_drivers", "driver:"+vehicle.getDriver().getId(), DriverStatus.AVAILABLE.getValue());
            }
            return null;
        }
    }
    @Override
    public String getTheRightAddr(String lat, String lng) {
        String latlng = lat + "," + lng;
        String url = "https://apis.map.qq.com/ws/geocoder/v1/?location=" + lat+","+lng +
                "&key=BG7BZ-ZN3K4-APUU7-FPDV6-CSJ3Z-MIFFK" +
                "&get_poi=0";
        String res = restTemplate.getForObject(url, String.class);
        ObjectMapper objectMapper = new ObjectMapper();
        String addr = "";
        try {
            Map<String,Object> map = objectMapper.readValue(res, Map.class);
            Map<String,Map<String,String>> addrMap =(Map<String, Map<String,String>>) map.get("result");
             addr = addrMap.get("formatted_addresses").get("recommend");
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return addr;
    }

    @Override
    public void sendEmail(String email) {
        refreshProducer.sendMail("SendEmail-" + email, MailRabbitConfig.MAIL_ROUTING_KEY);
    }

    @Override
    public void sendSms(String phoneNum) {
        refreshProducer.sendSms("SendSms-" + phoneNum, SmsRabbitConfig.SMS_ROUTING_KEY);
    }
}
